function [output] = poissonBlend(im_s,mask_s,im_background)
[imh, imw, nn] = size(im_background);
im2var = zeros(imh, imw);
im2var(1:imh*imw) = 1:imh*imw;
% mask_1의 x,y좌표값 가져오기 -> A의 ncol 계산하기
[y,x] = find(mask_s ~= 0);
[y_s,x_s] = find(mask_s == 0);
ncol = size(x,1)+size(x_s,1);
A = sparse([], [], [], ncol, nrow, 0);
output = zeros(imh,imw,nn);
t = im_background(:,:,c);
% 마스크 안은 source의 gradient를 따르도록 함.
% 단, 만약 boundary에 걸쳐있다면, target_j의 값과 source_i의 값 비교
A(e, im2var(y(i),x(i))) = 4;
if mask_s(y(i),x(i)-1) == 0
A(e, im2var(y(i),x(i)-1)) = 0;
right_term = right_term + s(y(i),x(i)) - s(y(i),x(i)-1) + t(y(i),x(i)-1);
A(e, im2var(y(i),x(i)-1)) = -1;
right_term = right_term + s(y(i),x(i)) - s(y(i),x(i)-1);
if mask_s(y(i),x(i)+1) == 0
A(e, im2var(y(i),x(i)+1)) = 0;
right_term = right_term + s(y(i),x(i)) - s(y(i),x(i)+1) + t(y(i),x(i)+1);
A(e, im2var(y(i),x(i)+1)) = -1;
right_term = right_term + s(y(i),x(i)) - s(y(i),x(i)+1);
if mask_s(y(i)-1,x(i)) == 0
A(e, im2var(y(i)-1,x(i))) = 0;
right_term = right_term + s(y(i),x(i)) - s(y(i)-1,x(i)) + t(y(i)-1,x(i));
A(e, im2var(y(i)-1,x(i))) = -1;
right_term = right_term + s(y(i),x(i)) - s(y(i)-1,x(i));
if mask_s(y(i)+1,x(i)) == 0
A(e, im2var(y(i)+1,x(i))) = 0;
right_term = right_term + s(y(i),x(i)) - s(y(i)+1,x(i)) + t(y(i)+1,x(i));
A(e, im2var(y(i)+1,x(i))) = -1;
right_term = right_term + s(y(i),x(i)) - s(y(i)+1,x(i));
%마스크 밖은 target의 pixel을 따르도록 함
A(e,im2var(y_s(i),x_s(i))) = 1;
function [output] = mixedBlend(im_s, mask_s, im_bg)
[imh, imw, nn] = size(im_bg);
im2var = zeros(imh, imw);
im2var(1:imh*imw) = 1:imh*imw;
% mask_1의 x,y좌표값 가져오기 -> A의 ncol 계산하기
[y,x] = find(mask_s ~= 0);
[y_s,x_s] = find(mask_s == 0);
ncol = size(x,1) + size(x_s,1);
A = sparse([], [], [], ncol, nrow, 0);
output = zeros(imh,imw,nn);
A(e, im2var(y(i),x(i))) = 4;
if mask_s(y(i),x(i)-1) == 0
A(e, im2var(y(i),x(i)-1)) = 0;
right_term = right_term + mix_compare(y(i),x(i),t,s,0,-1) + t(y(i),x(i)-1);
A(e, im2var(y(i),x(i)-1)) = -1;
right_term = right_term + mix_compare(y(i),x(i),t,s,0,-1);
if mask_s(y(i),x(i)+1) == 0
A(e, im2var(y(i),x(i)+1)) = 0;
right_term = right_term + mix_compare(y(i),x(i),t,s,0,1) + t(y(i),x(i)+1);
A(e, im2var(y(i),x(i)+1)) = -1;
right_term = right_term + mix_compare(y(i),x(i),t,s,0,1);
if mask_s(y(i)-1,x(i)) == 0
A(e, im2var(y(i)-1,x(i))) = 0;
right_term = right_term + mix_compare(y(i),x(i),t,s,-1,0) + t(y(i)-1,x(i));
A(e, im2var(y(i)-1,x(i))) = -1;
right_term = right_term + mix_compare(y(i),x(i),t,s,-1,0);
if mask_s(y(i)+1,x(i)) == 0
A(e, im2var(y(i)+1,x(i))) = 0;
right_term = right_term + mix_compare(y(i),x(i),t,s,1,0) + t(y(i)+1,x(i));
A(e, im2var(y(i)+1,x(i))) = -1;
right_term = right_term + mix_compare(y(i),x(i),t,s,1,0);
A(e,im2var(y_s(i),x_s(i))) = 1;
function [d] = mix_compare(y,x,t,s,a,b)
if abs(t(y,x)-t(y+a,x+b)) < abs(s(y,x)-s(y+a,x+b))
function [mask, poly] = getMask(im)
% [mask, poly] = getMask(im)
% Asks user to draw polygon around input image. Provides binary mask of
% polygon and a chain of all interior boundary points.
disp('Draw polygon around source object in clockwise order, q to stop')
figure(1), hold off, imagesc(im), axis image;
hold on, plot(sx, sy, '*-');
mask = poly2mask(sx, sy, size(im, 1), size(im, 2));
[poly.x, poly.y] = mask2chain(mask);
function [im_s2, mask2] = alignSource(im_s, mask, im_t,a)
% im_s2 = alignSource(im_s, mask, im_t)
% Asks user for bottom-center position and outputs an aligned source image.
figure(1), hold off, imagesc(im_s), axis image
figure(2), hold off, imagesc(im_t), axis image
y1 = min(y)-1; y2 = max(y)+1; x1 = min(x)-1; x2 = max(x)+1;
im_s2 = zeros(size(im_t));
disp('choose target bottom-center location')
yind2 = (yind -max(y))*a + round(ty);
xind2 = (xind - round(mean(x)))*a + round(tx);
y = (y - max(y))*a + round(ty);
x = (x - round(mean(x)))*a + round(tx);
ind = y + (x-1)*size(im_t, 1) ;
mask2 = false(size(im_t, 1), size(im_t, 2));
im_s2(yind2, xind2, :) = im_s(yind, xind, :);
im_t(repmat(mask2, [1 1 3])) = im_s2(repmat(mask2, [1 1 3]));
figure(1), hold off, imagesc(im_s2), axis image;
figure(2), hold off, imagesc(im_t), axis image;